

#include <stdio.h>
#include <string.h>
#include "rp2040.h"

#include "pico.h"
#include "hardware/structs/iobank0.h"
#include "hardware/structs/sio.h"
#include "hardware/structs/clocks.h"
#include "hardware/structs/uart.h"

/**/
#include "hardware/clocks.h"
#include "hardware/resets.h"
#include "hardware/gpio.h"

#include "dbg_cli.h"


void abort(void)
{
	while ( 1 )  {
		__asm ( "nop" );
	}
}

void SystemInit( void )
{
	clocks_init();


	/**/
	extern char __bss_end;
	extern void miniheap_init(void *ptr, size_t len);
	uintptr_t  tptr;

	/**/
	tptr = (uintptr_t)&__bss_end;
	miniheap_init( (void *)tptr, (0x20040000 - tptr) );


	/* peri clock */
	clock_hw_t * pclk;

	pclk = &clocks_hw->clk[clk_peri];
	hw_clear_bits( &pclk->ctrl, CLOCKS_CLK_PERI_CTRL_ENABLE_BITS );
	pclk->div = 1 << CLOCKS_CLK_GPOUT0_DIV_INT_LSB;
	pclk->ctrl = CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_XOSC_CLKSRC << CLOCKS_CLK_PERI_CTRL_AUXSRC_LSB;
	hw_set_bits( &pclk->ctrl, CLOCKS_CLK_PERI_CTRL_ENABLE_BITS );

	return;
}

void tttdelay( uint32_t cnt )
{
	uint32_t  i;

	for (i=0; i<cnt; i++ ) {
		__NOP();
	}
}


void tttclockout( void )
{
	clock_hw_t * pclk;

	/* clock out */
	pclk = &clocks_hw->clk[clk_gpout0];
	pclk->div = 2 << CLOCKS_CLK_GPOUT0_DIV_INT_LSB;
	pclk->ctrl = CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_VALUE_ROSC_CLKSRC << CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_LSB;
	hw_set_bits( &pclk->ctrl, CLOCKS_CLK_GPOUT0_CTRL_ENABLE_BITS );

	/* uart0,  clock enable */
	hw_set_bits( &clocks_hw->wake_en1, CLOCKS_WAKE_EN1_CLK_SYS_UART0_BITS | CLOCKS_WAKE_EN1_CLK_PERI_UART0_BITS );
}


/* 8N1, 115200 */
void ttt_uart0_init( void )
{
	uart0_hw->ibrd = 6;
	uart0_hw->fbrd = 33;
	uart0_hw->lcr_h = UART_UARTLCR_H_WLEN_BITS | UART_UARTLCR_H_FEN_BITS;
	uart0_hw->cr = UART_UARTCR_UARTEN_BITS | UART_UARTCR_TXE_BITS | UART_UARTCR_RXE_BITS;
	uart0_hw->dmacr = UART_UARTDMACR_TXDMAE_BITS | UART_UARTDMACR_RXDMAE_BITS;
}



static uint32_t ttt_ticks = 0;

void  SysTick_Handler( void )
{

	ttt_ticks += 1;

	if ( ttt_ticks & 0x1 )  {
		gpio_put( 25, true );
	} else {
		gpio_put( 25, false );
	}
	return;
}



int  ttt_cmd_cpsr( void * pctx, int argc, const char **argv )
{
	int  iret;
	uint32_t  temp;

	if ( argc < 2 )  {
		printf( "ticks = %u\n", ttt_ticks );
		goto usage;
	}


	/**/
	iret = debug_str2uint( argv[1], &temp );
	if ( iret != 0 )  {
		printf( "arg1, fmt err, %d\n", iret );
		goto usage;
	}

	switch (temp ) {
	case 0:
		temp = __get_CONTROL();
		printf( "control : %X\n", temp );
		break;
		
	case 1:
		temp = __get_xPSR();
		printf( "xpsr : %X\n", temp );
		break;

	case 2:
		temp = __get_PRIMASK();
		printf( "primask : %X\n", temp );
		break;

	default:
		break;
	}

	/**/
	return 0;

usage:
	printf("%s <0-3>\n", argv[0]);
	return 0;
}




extern void  con_proc_input( void );

int main( void )
{
	uint32_t  temp;

	/**/
	tttclockout();

	/* un reset */
	unreset_block_wait( RESETS_RESET_IO_BANK0_BITS );
	unreset_block_wait( RESETS_RESET_UART0_BITS );
	
	/* gpio16:uart0-tx,  gpio17:uart0-rx */
	gpio_pull_up( 12 );
	gpio_pull_up( 13 );
	gpio_set_function( 12, GPIO_FUNC_UART );
	gpio_set_function( 13, GPIO_FUNC_UART );

	/**/
	ttt_uart0_init();

	/**/
	gpio_set_function( 21, GPIO_FUNC_GPCK );
	gpio_set_function( 25, GPIO_FUNC_SIO );

	/**/
	gpio_set_dir( 25, true );
	
	/**/
	SysTick_Config( 9000000 );

	/**/
	debug_cli_init();
	debug_add_cmd( "cpsr", ttt_cmd_cpsr, 		NULL );
	printf("hello...\n");

	/**/
	while ( 1 )  {

		con_proc_input();

		gpio_put( 25, true );

		tttdelay(100000);

		gpio_put( 25, false );
		printf("hel2222\n");
		tttdelay(100000);
	}

	
	return 0;
}

